
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       ap_log.h
  * @author     baiyang
  * @date       2023-2-23
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include "log_structure.h"

#include <float.h>
#include <stdint.h>
#include <stdbool.h>

#include <pid/pid_info.h>
#include <mission/mb_mission.h>
#include <common/location/location.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
typedef void (*aplog_vehicle_startup_message)(void); 

enum ApLogOriginType {
    APLOG_EKF_ORIGIN = 0,
    APLOG_AHRS_HOME = 1
};

enum AplogStage {
    APLOG_FORMATS = 0,
    APLOG_UNITS,
    APLOG_MULTIPLIERS,
    APLOG_FORMAT_UNITS,
    APLOG_PARMS,
    APLOG_VEHICLE_MESSAGES,
    APLOG_RUNNING_SUBWRITERS, // must be last thing to run as we can redo bits of these
    APLOG_DONE,
};

// do not do anything here apart from add stuff; maintaining older
// entries means log analysis is easier
enum LogEvent {
    LOG_EVENT_ARMED = 10,
    LOG_EVENT_DISARMED = 11,
    LOG_EVENT_AUTO_ARMED = 15,
    LOG_EVENT_LAND_COMPLETE_MAYBE = 17,
    LOG_EVENT_LAND_COMPLETE = 18,
    LOG_EVENT_NOT_LANDED = 28,
    LOG_EVENT_LOST_GPS = 19,
    LOG_EVENT_FLIP_START = 21,
    LOG_EVENT_FLIP_END = 22,
    LOG_EVENT_SET_HOME = 25,
    LOG_EVENT_SET_SIMPLE_ON = 26,
    LOG_EVENT_SET_SIMPLE_OFF = 27,
    LOG_EVENT_SET_SUPERSIMPLE_ON = 29,
    LOG_EVENT_AUTOTUNE_INITIALISED = 30,
    LOG_EVENT_AUTOTUNE_OFF = 31,
    LOG_EVENT_AUTOTUNE_RESTART = 32,
    LOG_EVENT_AUTOTUNE_SUCCESS = 33,
    LOG_EVENT_AUTOTUNE_FAILED = 34,
    LOG_EVENT_AUTOTUNE_REACHED_LIMIT = 35,
    LOG_EVENT_AUTOTUNE_PILOT_TESTING = 36,
    LOG_EVENT_AUTOTUNE_SAVEDGAINS = 37,
    LOG_EVENT_SAVE_TRIM = 38,
    LOG_EVENT_SAVEWP_ADD_WP = 39,
    LOG_EVENT_FENCE_ENABLE = 41,
    LOG_EVENT_FENCE_DISABLE = 42,
    LOG_EVENT_ACRO_TRAINER_OFF = 43,
    LOG_EVENT_ACRO_TRAINER_LEVELING = 44,
    LOG_EVENT_ACRO_TRAINER_LIMITED = 45,
    LOG_EVENT_GRIPPER_GRAB = 46,
    LOG_EVENT_GRIPPER_RELEASE = 47,
    LOG_EVENT_PARACHUTE_DISABLED = 49,
    LOG_EVENT_PARACHUTE_ENABLED = 50,
    LOG_EVENT_PARACHUTE_RELEASED = 51,
    LOG_EVENT_LANDING_GEAR_DEPLOYED = 52,
    LOG_EVENT_LANDING_GEAR_RETRACTED = 53,
    LOG_EVENT_MOTORS_EMERGENCY_STOPPED = 54,
    LOG_EVENT_MOTORS_EMERGENCY_STOP_CLEARED = 55,
    LOG_EVENT_MOTORS_INTERLOCK_DISABLED = 56,
    LOG_EVENT_MOTORS_INTERLOCK_ENABLED = 57,
    LOG_EVENT_ROTOR_RUNUP_COMPLETE = 58, // Heli only
    LOG_EVENT_ROTOR_SPEED_BELOW_CRITICAL = 59, // Heli only
    LOG_EVENT_EKF_ALT_RESET = 60,
    LOG_EVENT_LAND_CANCELLED_BY_PILOT = 61,
    LOG_EVENT_EKF_YAW_RESET = 62,
    LOG_EVENT_AVOIDANCE_ADSB_ENABLE = 63,
    LOG_EVENT_AVOIDANCE_ADSB_DISABLE = 64,
    LOG_EVENT_AVOIDANCE_PROXIMITY_ENABLE = 65,
    LOG_EVENT_AVOIDANCE_PROXIMITY_DISABLE = 66,
    LOG_EVENT_GPS_PRIMARY_CHANGED = 67,
    // 68, 69, 70 were winch events
    LOG_EVENT_ZIGZAG_STORE_A = 71,
    LOG_EVENT_ZIGZAG_STORE_B = 72,
    LOG_EVENT_LAND_REPO_ACTIVE = 73,
    LOG_EVENT_STANDBY_ENABLE = 74,
    LOG_EVENT_STANDBY_DISABLE = 75,

    LOG_EVENT_FENCE_FLOOR_ENABLE = 80,
    LOG_EVENT_FENCE_FLOOR_DISABLE = 81,

    // if the EKF's source input set is changed (e.g. via a switch or
    // a script), we log an event:
    LOG_EVENT_EK3_SOURCES_SET_TO_PRIMARY = 85,
    LOG_EVENT_EK3_SOURCES_SET_TO_SECONDARY = 86,
    LOG_EVENT_EK3_SOURCES_SET_TO_TERTIARY = 87,

    LOG_EVENT_AIRSPEED_PRIMARY_CHANGED = 90,

    LOG_EVENT_SURFACED = 163,
    LOG_EVENT_NOT_SURFACED = 164,
    LOG_EVENT_BOTTOMED = 165,
    LOG_EVENT_NOT_BOTTOMED = 166,
};

enum LogDataID {
    LOG_DATA_AP_STATE = 7,
//  LOG_DATA_SYSTEM_TIME_SET = 8,
    LOG_DATA_INIT_SIMPLE_BEARING = 9,
};

enum LogErrorSubsystem {
    LogErrorSubsystemMAIN = 1,
    LogErrorSubsystemRADIO = 2,
    LogErrorSubsystemCOMPASS = 3,
    LogErrorSubsystemOPTFLOW = 4,   // not used
    LogErrorSubsystemFAILSAFE_RADIO = 5,
    LogErrorSubsystemFAILSAFE_BATT = 6,
    LogErrorSubsystemFAILSAFE_GPS = 7,   // not used
    LogErrorSubsystemFAILSAFE_GCS = 8,
    LogErrorSubsystemFAILSAFE_FENCE = 9,
    LogErrorSubsystemFLIGHT_MODE = 10,
    LogErrorSubsystemGPS = 11,
    LogErrorSubsystemCRASH_CHECK = 12,
    LogErrorSubsystemFLIP = 13,
    LogErrorSubsystemAUTOTUNE = 14,  // not used
    LogErrorSubsystemPARACHUTES = 15,
    LogErrorSubsystemEKFCHECK = 16,
    LogErrorSubsystemFAILSAFE_EKFINAV = 17,
    LogErrorSubsystemBARO = 18,
    LogErrorSubsystemCPU = 19,
    LogErrorSubsystemFAILSAFE_ADSB = 20,
    LogErrorSubsystemTERRAIN = 21,
    LogErrorSubsystemNAVIGATION = 22,
    LogErrorSubsystemFAILSAFE_TERRAIN = 23,
    LogErrorSubsystemEKF_PRIMARY = 24,
    LogErrorSubsystemTHRUST_LOSS_CHECK = 25,
    LogErrorSubsystemFAILSAFE_SENSORS = 26,
    LogErrorSubsystemFAILSAFE_LEAK = 27,
    LogErrorSubsystemPILOT_INPUT = 28,
    LogErrorSubsystemFAILSAFE_VIBE = 29,
    LogErrorSubsystemINTERNAL_ERROR = 30,
    LogErrorSubsystemFAILSAFE_DEADRECKON = 31
};

// bizarrely this enumeration has lots of duplicate values, offering
// very little in the way of typesafety
enum LogErrorCode {
// general error codes
    LogErrorCodeERROR_RESOLVED  = 0,
    LogErrorCodeFAILED_TO_INITIALISE = 1,
    LogErrorCodeUNHEALTHY = 4,
// subsystem specific error codes -- radio
    LogErrorCodeRADIO_LATE_FRAME = 2,
// subsystem specific error codes -- failsafe_thr, batt, gps
    LogErrorCodeFAILSAFE_RESOLVED = 0,
    LogErrorCodeFAILSAFE_OCCURRED = 1,
// subsystem specific error codes -- main
    LogErrorCodeMAIN_INS_DELAY = 1,
// subsystem specific error codes -- crash checker
    LogErrorCodeCRASH_CHECK_CRASH = 1,
    LogErrorCodeCRASH_CHECK_LOSS_OF_CONTROL = 2,
// subsystem specific error codes -- flip
    LogErrorCodeFLIP_ABANDONED = 2,
// subsystem specific error codes -- terrain
    LogErrorCodeMISSING_TERRAIN_DATA = 2,
// subsystem specific error codes -- navigation
    LogErrorCodeFAILED_TO_SET_DESTINATION = 2,
    LogErrorCodeRESTARTED_RTL = 3,
    LogErrorCodeFAILED_CIRCLE_INIT = 4,
    LogErrorCodeDEST_OUTSIDE_FENCE = 5,
    LogErrorCodeRTL_MISSING_RNGFND = 6,
    // subsystem specific error codes -- internal_error
    LogErrorCodeINTERNAL_ERRORS_DETECTED = 1,

// parachute failed to deploy because of low altitude or landed
    LogErrorCodePARACHUTE_TOO_LOW = 2,
    LogErrorCodePARACHUTE_LANDED = 3,
// EKF check definitions
    LogErrorCodeEKFCHECK_BAD_VARIANCE = 2,
    LogErrorCodeEKFCHECK_VARIANCE_CLEARED = 0,
// Baro specific error codes
    LogErrorCodeBARO_GLITCH = 2,
    LogErrorCodeBAD_DEPTH = 3, // sub-only
// GPS specific error coces
    LogErrorCodeGPS_GLITCH = 2,
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void aplog_init(const struct LogStructure *structure, uint16_t len);
bool aplog_should_log(const uint32_t mask);
void aplog_start();
void aplog_stop();
void aplog_write_more_startup_messages();
static inline float aplog_quiet_nanf() { return nanf("0x4152"); } // "AR"
static inline double aplog_quiet_nan() { return nan("0x4152445550490a"); } // "ARDUPI"

bool aplog_write_message(const char *message);
void aplog_write_messageF(const char *fmt, ...);

void aplog_fill_format(const struct LogStructure *structure, struct log_Format *pkt);
void aplog_fill_format_units(const struct LogStructure *s, struct log_Format_Units *pkt);
bool aplog_write_format(const struct LogStructure *s);
bool aplog_write_unit(const struct UnitStructure *s);
bool aplog_write_multiplier(const struct MultiplierStructure *s);
bool aplog_write_format_units(const struct LogStructure *s);
bool aplog_write_parameter(const char *name, float value, float default_val);
void aplog_set_vehicle_startup_writer(aplog_vehicle_startup_message writer);
bool aplog_write_vehicle_messages();


///
void aplog_write_imu();
void aplog_write_acc(const uint8_t instance, const uint64_t sample_us, const float accel[3]);
void aplog_write_gyr(const uint8_t instance, const uint64_t sample_us, const float gyro[3]);
void aplog_write_imu_fast();
void aplog_write_vibration();
void aplog_write_baro();
void aplog_write_mag();
void aplog_write_write_gps();
void aplog_write_attitude();
void aplog_write_pos();
void aplog_write_psc_ne();
void aplog_write_psc_d();
void aplog_write_rcin();
void aplog_write_rcout();
bool aplog_write_mode(uint8_t mode, const uint8_t reason);
void aplog_write_event(enum LogEvent event_id);
bool aplog_write_mission_cmd(mission_command_const_t cmd);
void aplog_write_ekf_innovation();
void aplog_write_ekf_status();
void aplog_write_estimator_sensor_bias();
void aplog_write_yaw_estimator_status();
void aplog_write_origin(enum ApLogOriginType origin_type, const Location *loc);
void aplog_write_pid(uint8_t msg_type, pid_info_const_t info);
void aplog_write_airspeed();
/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



